#include <QtOpenGL>
#include <QVector3D>
#include "placa.h"
#include "testmesh.h"
#include "node.h"
#include "mesh.h"
#include "cassert"
#include <QDebug>
#include <iostream>
#include <armadillo>

using namespace arma;

placa::placa(const QVector3D& center, QObject *parent):
    Object3D(center, parent),  malha(10,20,0.0,0.0,0.1,0.1)
{
    nNosX = malha.getNElementsX() + 1;
    nNosY = malha.getNElementsY() + 1;

    boundaryCondition();
    computeDeslocation();

    meshControl = true;
}

void placa::drawGeometry()
{
    origin();
    if (meshControl ==true)
    {
        drawMesh();
    }else
    {
        drawDeformedMesh();
    }
}

void placa::origin()
{
    glDisable( GL_LIGHTING );
    glBegin( GL_LINES );
        glColor3f(1.0, 0.0, 0.0);
        glVertex3f(0.0, 0.0, 0.0);
        glVertex3f(1.0, 0.0, 0.0);

        glColor3f(0.0, 1.0, 0.0);
        glVertex3f(0.0, 0.0, 0.0);
        glVertex3f(0.0, 1.0, 0.0);

        glColor3f(0.0, 0.0, 1.0);
        glVertex3f(0.0, 0.0, 0.0);
        glVertex3f(0.0, 0.0, 1.0);
    glEnd();
    glEnable( GL_LIGHTING );
}

void placa::drawMesh()
{
    float x,y;

    glDisable( GL_LIGHTING );
    glBegin(GL_QUADS);
        glColor3f(0.0, 0.0, 1.0);

        for (int i = 1; i <= malha.getNElementsX()*malha.getNElementsY() ; i++)
        {

            x = malha.getElement(i).getNode(1)->getPositionX();
            y = malha.getElement(i).getNode(1)->getPositionY();
            glVertex3f(x,y,0.0);

            x = malha.getElement(i).getNode(2)->getPositionX();
            y = malha.getElement(i).getNode(2)->getPositionY();
            glVertex3f(x,y,0.0);

            x = malha.getElement(i).getNode(3)->getPositionX();
            y = malha.getElement(i).getNode(3)->getPositionY();
            glVertex3f(x,y,0.0);

            x = malha.getElement(i).getNode(4)->getPositionX();
            y = malha.getElement(i).getNode(4)->getPositionY();
            glVertex3f(x,y,0.0);
        }

    glEnd();
    glEnable( GL_LIGHTING );
}

void placa::drawDeformedMesh()
{

    float x,y;

    glDisable( GL_LIGHTING );
    glBegin(GL_QUADS);
        glColor3f(0.0, 0.0, 1.0);

        for (int i = 1; i <= malha.getNElementsX()*malha.getNElementsY() ; i++)
        {

            x = malha.getElement(i).getNode(1)->getPositionX() + malha.getElement(i).getNode(1)->getHorizontalDeslocation();
            y = malha.getElement(i).getNode(1)->getPositionY() + malha.getElement(i).getNode(1)->getVerticalDeslocation();
            glVertex3f(x,y,0.0);

            x = malha.getElement(i).getNode(2)->getPositionX() + malha.getElement(i).getNode(2)->getHorizontalDeslocation();
            y = malha.getElement(i).getNode(2)->getPositionY() + malha.getElement(i).getNode(2)->getVerticalDeslocation();
            glVertex3f(x,y,0.0);

            x = malha.getElement(i).getNode(3)->getPositionX() + malha.getElement(i).getNode(3)->getHorizontalDeslocation();
            y = malha.getElement(i).getNode(3)->getPositionY() + malha.getElement(i).getNode(3)->getVerticalDeslocation();
            glVertex3f(x,y,0.0);

            x = malha.getElement(i).getNode(4)->getPositionX() + malha.getElement(i).getNode(4)->getHorizontalDeslocation();
            y = malha.getElement(i).getNode(4)->getPositionY() + malha.getElement(i).getNode(4)->getVerticalDeslocation();
            glVertex3f(x,y,0.0);
        }

    glEnd();
    glEnable( GL_LIGHTING );
}

void placa::computeDeslocation()
{

    malha.setGlobalMatrixNumerationXY();

    malha.setGlobalMatrix();
    malha.setGlobalForce();

    mat globalMatrix = malha.getGlobalMatrix();
    mat globalForce = malha.getGlobalForce();

    vec deslocation = solve(globalMatrix,globalForce);
    malha.setNodeDeslocation(deslocation);
    malha.setNodeDeformation();
    malha.setNodeDeformationAnal();



    for(int i = 0; i<200 ; i++)
    {
        mat aux = zeros(2,2);
        aux = abs(malha.getNode(i).getDeformationAnal() - malha.getNode(i).getDeformation());
        cout << aux << '\n';
    }


}

void placa::boundaryCondition()
{
    float x=0.0,y=0.0;
    for (int i = 1; i <= nNosX*nNosY ; i++)
    {
        x = malha.getNode(i).getPositionX();
        y = malha.getNode(i).getPositionY();
        if(x < 0.01)
        {
            malha.getNode(i).setBoundaryCondition(1,1,0,0,cos(datum::pi *y)/(datum::pi *datum::pi ),0.0,0.0,0.0);
        }else if(x > 0.99)
        {
            malha.getNode(i).setBoundaryCondition(1,1,0,0,-cos(datum::pi *y)/(datum::pi *datum::pi ),0.0,0.0,0.0);
        }else if(y < 0.01)
        {
            malha.getNode(i).setBoundaryCondition(1,1,0,0,cos(datum::pi *x)/(datum::pi *datum::pi ),0.0,0.0,0.0);
        }else if(y > 1.99)
        {
            malha.getNode(i).setBoundaryCondition(1,1,0,0,cos(datum::pi *x)/(datum::pi *datum::pi ),0.0,0.0,0.0);
        }else
        {
            malha.getNode(i).setBoundaryCondition(0,0,0,0,0.0,0.0,0.0,0.0);
        }
    }
}

void placa::setMeshControl(bool a)
{
    meshControl = a;
}
